﻿package com.vigmonk.utils
{
	import flash.display.DisplayObject;	
	import flash.events.Event;
	import flash.utils.getTimer;
	import flash.display.Sprite;

	public class TweenManager{
		
		private static var enterObj:Sprite;
		private static var tweenArr:Array;
		private static var currentTime:Number;
		
		public function TweenManager():void{}

		// TweenManager.tween(mc,{},Strong.easeOut,1,{onStart:startFn,onStartParam:['a'],onFinish:comp,onFinishParam:['b']});
		
		public static function tween(_target:DisplayObject,_prop:Object,_easeFn:Function,_duration:Number,_func:Object=null):void
		{
			var overlapBln:uint = 1;
			
			if(tweenArr==null) tweenArr = new Array();
			if(enterObj==null){
				currentTime	  	= getTimer();
				enterObj 		= new Sprite();
				enterObj.addEventListener(Event.ENTER_FRAME,enterFn);
			}
			
			var obj:Object 	= new Object();
			obj.target 		= _target;
			obj.prop 		= _prop;
			obj.ease 		= _easeFn;		
			obj.duration 	= _duration*1000;	
			obj.startTime 	= currentTime;
			obj.pause		= false;
			obj.func 		= _func;
			propOverride(obj);
			
			if(_func!=null) callOnStartFn(_func);
			
			for( var prop in obj.prop){
				if(_target[prop]!=_prop[prop]) overlapBln*=0;
				obj[prop] = _target[prop];
			}
			
			// 목표값이랑 같으면, 추가 안시킴.
			if(!overlapBln)tweenArr.push(obj);
		}
		
		private static function propOverride(_obj:Object):void
		{
			var num:Number;
			
			for(var i:uint=0;i<tweenArr.length;i++){
				var exTween:Object = tweenArr[i];
				
				if(exTween.target==_obj.target){
					for (var prop in _obj.prop ){
						if (exTween[prop]!= null ){
							delete exTween.prop[prop];
						}
					}

					num = 0;
					for( var a in exTween.prop){
						num ++;
						return;
					}
					
					if(num==0){
						tweenArr.splice(i,1);
					}
				}
			}
		}
		
		// tween start, Call Function
		private static function callOnStartFn(_fn):void
		{
			if(_fn.onStart!=null){
				_fn.onStart.apply(null, _fn.onStartParam);
			}
		}
		
		// tween Finish, Call Function
		private static function callOnFinishFn(_fn):void
		{
			if(_fn.onFinish!=null){
				_fn.onFinish.apply(null, _fn.onFinishParam);
			}
		}
		
		private static function enterFn(_e:Event):void
		{
			currentTime	= getTimer();
			
			var curTween:Object;
			var target:DisplayObject;
			var easeFn:Function;
			var time:Number; 
			
			var begin:Number; 
			var end:Number; 
			
			var duration:Number;
			
			if(tweenArr.length==0)removeTween();
			
			for(var i:uint=0;i<tweenArr.length;i++){
				
				curTween 	= tweenArr[i];
				target	 	= curTween.target;
				easeFn	 	= curTween.ease;
				
				time 		= currentTime - curTween.startTime;
				duration	= curTween.duration;
				
				if(time<duration){
					for( var prop in curTween.prop){
						begin 		= curTween[prop];
						end			= curTween.prop[prop] - begin;
						target[prop] = easeFn(time,begin,end,duration);
					}
				}else{
					//trace('TWEEN REMOVE');
					if(curTween.func!=null) callOnFinishFn(curTween.func);
					tweenArr.splice(i,1);
					if(tweenArr.length==0){						
						removeTween();
					}
				}
			}
		}
		
		private static function removeTween():void
		{
			//trace('[TWEEN REMOVE ALL]');
			enterObj.removeEventListener(Event.ENTER_FRAME,enterFn);
			if(enterObj!=null) enterObj = null;
			if(tweenArr!=null) tweenArr = [];
		}
		
		public static function tweenStop(_target:DisplayObject):void
		{
			var i:uint = 0;
			
			if(tweenArr!=null){
				while(i<tweenArr.length){
					if(tweenArr[i].target === _target){
						tweenArr.splice(i,1);
						break;
					}
					i++;
				}
			}
		}
	}	
}